// sqdll.h : main header file for the sqdll DLL
//

#pragma once

#ifndef __AFXWIN_H__
	#error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h"		// main symbols


// CsqdllApp
// See sqdll.cpp for the implementation of this class
//
typedef class CSquirrelVM;

typedef void (CSquirrelVM::*SQVM_MEMBER_PRINT_FN)(HSQUIRRELVM,const SQChar * ,...);
typedef void (*SQVM_EXTERN_PRINT_FN)(CSquirrelVM *, const SQChar *);
typedef void (*__cdecl SQVM_PRINT_STRING)(LPCSTR);

void bypass_error_function(HSQUIRRELVM vm, const SQChar *s, va_list);
void bypass_print_function(HSQUIRRELVM vm, const SQChar *s, va_list);

class CsqdllApp : public CWinApp
{
public:
	CsqdllApp();

// Overrides
public:
	virtual BOOL InitInstance();

	DECLARE_MESSAGE_MAP()
};

class __declspec(dllexport) CSquirrelVM
{
private:
	HSQUIRRELVM				_vm;
	SQVM_MEMBER_PRINT_FN	_prnFnInternal;
	SQVM_EXTERN_PRINT_FN	_prnFnExternal;
	SQVM_MEMBER_PRINT_FN	_errFnInternal;
	SQVM_EXTERN_PRINT_FN	_errFnExternal;

private:
	/*
	** Print Wrappers
	*/
	void PrintInternal(HSQUIRRELVM,const SQChar * ,...);
	void ErrorInternal(HSQUIRRELVM,const SQChar * ,...);

public:
	CSquirrelVM();

	void Open(int initialStackSize);
	bool IsOpen();
	void Close();

	SQUserPointer GetForeignPtr();
	SQUserPointer GetPrintFunc();
	SQUserPointer GetErrorFunc();

	HSQUIRRELVM GetVM();

	SQInteger GetVMState();
	void Move(CSquirrelVM* tarVM, SQInteger idx);
	CSquirrelVM* NewThread(CSquirrelVM* , SQInteger intialStackSize);
	void PushRegistryTable();
	void PushRootTable();
	void SetErrorHandler();
	void SetForeignPtr(SQUserPointer p);
	void SetPrintFunc(SQVM_EXTERN_PRINT_FN prnFn, SQVM_EXTERN_PRINT_FN errFn);
	void SetRootTable();
	SQRESULT SuspendVM();
	SQRESULT WakeUpVM(SQBool resumedret, SQBool retval, SQBool RaiseError,SQBool ThrowError);

	/*
	** COMPILER
	*/
	SQRESULT CompileReader(SQLEXREADFUNC ReadFunc, SQUserPointer UserPtr, char *SourceName, SQBool RaiseError );
	SQRESULT CompileBuffer(char *Buffer, int BufferSize, char *SourceName, SQBool RaiseError );
	void EnableDebugInfo(SQBool DebugInfo );
	void SetCompilerErrorHandler(SQCOMPILERERROR f );

	/*
	** STACK OPERATIONS
	*/
	SQInteger Cmp();
	SQInteger GetTop();
	void Pop(SQInteger Count);
	void PopTop();
	void Push(SQInteger Count);
	void Remove(SQInteger Count);
	void ReserveStack(SQInteger Count);
	void SetTop(SQInteger Count);

	/*
	** Object Creation and Handling
	*/
	SQRESULT CreateInstance(SQInteger Idx);
	SQRESULT GetBool(SQInteger Idx, SQBool *Result);
	SQRESULT GetClosureInfo(SQInteger Idx, SQUnsignedInteger *nparams, SQUnsignedInteger *nfreevars);
	SQRESULT GetFloat(SQInteger Idx, SQFloat *Result);
	SQRESULT GetInstanceUp(SQInteger Idx, SQUserPointer *up, SQUserPointer typeTag );
	SQRESULT GetInteger(SQInteger Idx, SQInteger *Result);
	SQChar * GetScratchPad(SQInteger minsize);
	SQInteger GetSize(SQInteger Idx);
	SQInteger GetString(SQInteger Idx, const SQChar **c);
	SQInteger GetThread(SQInteger Idx, HSQUIRRELVM *v);
	SQObjectType GetType(SQInteger Idx);
	SQRESULT GetTypeTag(SQInteger Idx, SQUserPointer *typetag);
	SQRESULT GetUserData(SQInteger Idx, SQUserPointer *p, SQUserPointer *typetag);
	SQRESULT GetUserPointer(SQInteger Idx, SQUserPointer *p);
	void NewArray(SQInteger Size);
	SQRESULT NewClass(SQBool HasBaseClass);
	void NewClosure(SQFUNCTION func, SQInteger nfreevars );
	void NewTable();
	SQUserPointer NewUserData(SQUnsignedInteger Size);
	void PushBool(SQBool Value );
	void PushFloat(SQFloat Value );
	void PushInteger(SQInteger Value );
	void PushNull();
	void PushString(const SQChar *s, SQInteger len);
	void PushUserPointer(SQUserPointer p);
	SQRESULT SetInstanceUp(SQInteger Idx, SQUserPointer up);
	SQRESULT SetNativeClosureName(SQInteger Idx, const SQChar *name);
	SQRESULT SetParamsCheck(SQInteger nparamscheck, const SQChar *TypeMask);
	void SetReleaseHook(SQInteger Idx, SQRELEASEHOOK Hook);
	SQRESULT SetTypeTag(SQInteger Idx, SQUserPointer TypeTag);
	SQRESULT Call(SQInteger Params, SQBool RetVal, SQBool RaiseError);
	void GetLastError();
	const SQChar * GetLocal(SQUnsignedInteger level, SQUnsignedInteger nseq );
	void ResetError();
	SQRESULT Resume(SQBool RetVal, SQBool RaiseError);
	SQRESULT ThrowError(const SQChar *err);


	/*
	** OBJECTS MANIPULATION
	*/
	SQRESULT ArrayAppend(SQInteger Idx);
	SQRESULT ArrayPop(SQInteger Idx, SQBool PushVal );
	SQRESULT ArrayResize(SQInteger Idx, SQInteger NewSize );
	SQRESULT ArrayReverse(SQInteger Idx );
	SQRESULT Clone(SQInteger Idx );
	SQRESULT CreateSlot(SQInteger Idx );
	SQRESULT DeleteSlot(SQInteger Idx, SQBool PushValue );
	SQRESULT Get(SQInteger Idx );
	SQRESULT GetAttributes(SQInteger Idx );
	SQRESULT GetClass(SQInteger Idx );
	SQRESULT GetDelegate(SQInteger Idx );
	const SQChar * GetFreeVariable(SQInteger Idx, SQInteger nval );
	SQRESULT GetWeakRefVal(SQInteger Idx );
	SQRESULT Next(SQInteger Idx );
	SQRESULT RawDeleteSlot(SQInteger Idx, SQBool PushVal );
	SQRESULT RawGet(SQInteger Idx );
	SQRESULT RawSet(SQInteger Idx );
	SQRESULT Set(SQInteger Idx );
	SQRESULT SetAttributes(SQInteger Idx );
	SQRESULT SetDelegate(SQInteger Idx );
	SQRESULT SetFreeVariable(SQInteger Idx, SQInteger nval );
	void WeakRef(SQInteger Idx );


	/*
	** ByteCode Serialization
	*/
	SQRESULT ReadClosure(SQREADFUNC readf, SQUserPointer up);
	SQRESULT WriteClosure(SQWRITEFUNC writef, SQUserPointer up);

	/*
	** RAW OBJECT HANDLING
	*/
	void AddRef(HSQOBJECT *po);
	SQRESULT GetObjTypeTag(HSQOBJECT *o, SQUserPointer *typetag);
	SQRESULT GetStackObj(SQInteger Idx, HSQOBJECT *po);
	SQBool ObjToBool(HSQOBJECT *po);
	SQFloat ObjToFloat(HSQOBJECT *po);
	SQInteger ObjToInteger(HSQOBJECT *po);
	const SQChar* ObjToString(HSQOBJECT *po);
	void PushObject(HSQOBJECT obj);
	SQBool Release(HSQOBJECT *po);
	void ResetObject(HSQOBJECT *po);

	/*
	** DEBUG INTERFACE
	*/
	void SetDebugHook();
	SQRESULT StackInfos(SQInteger Idx, SQStackInfos *si);

	bool Success(SQRESULT result);
	bool Failed(SQRESULT result);
};